package com.syqc.monitor.ui.historyline

import android.view.Gravity
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.recyclerview.widget.GridLayoutManager
import autodispose2.autoDispose
import com.haibin.calendarview.Calendar
import com.haibin.calendarview.CalendarView.OnCalendarSelectListener
import com.syqc.base.BaseTimeActivity
import com.syqc.choose.car.ChooseCarActivity
import com.syqc.choose.teamcar.TeamsCarsActivity
import com.syqc.comlib.custom.timer.CustomDatePicker
import com.syqc.comlib.custom.timer.DateFormatUtils
import com.syqc.comlib.rx.filterFast
import com.syqc.comlib.utils.ActivityResultUtil.launchAct
import com.syqc.comlib.utils.ActivityResultUtil.registerResultOk
import com.syqc.comlib.utils.CalendarUtil
import com.syqc.comlib.utils.ToolbarHelper
import com.syqc.comlib.utils.startActivityTo
import com.syqc.entity.DayMile
import com.syqc.monitor.ParamsUtil
import com.syqc.monitor.R
import com.syqc.monitor.databinding.ActivityHistoryLineBinding
import com.syqc.monitor.ui.carmonitor.HistoryLineViewModel
import com.syqc.adapter.ChooseTimeAdapter
import com.syqc.utils.Keys
import com.syqc.utils.NetDataUtil
import com.syqc.utils.TimeUtil

/**
 *@Author Jasper
 *@Time   2020/11/30
 *@Desc   历史轨迹
 */
class HistoryLineActivity :
    BaseTimeActivity<ActivityHistoryLineBinding>(ActivityHistoryLineBinding::inflate) {
    private val yearDesc by lazy { getString(R.string.unit_year) }
    private val monthDesc by lazy { getString(R.string.unit_month) }
    private val total by lazy { getString(R.string.desc_total) }
    private val mViewModel: HistoryLineViewModel by viewModels()

    private val mPopup by lazy { HistoryPopup(this) }

    //当前年+月
    private val curYM by lazy { CalendarUtil.getCurYM() }
    private var changYM = 0
    private var calendarS: String = ""
    private var calendarE: String = ""

    override fun initView() {
        super.initView()
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
        ToolbarHelper.setToolbar(this, R.string.title_monitor_history_line)
        binding.rgbType.isSelected = true
        initIntent()
        setParams()
        binding.tvThresholdSpeed.text = "${getString(R.string.desc_run_speed)}≥"
        binding.tvThresholdStop.text = "${getString(R.string.desc_stop_time)}≥"

        mRecyclerVB.recyclerWrap.layoutManager = GridLayoutManager(this, 4)
        mRecyclerVB.recyclerWrap.adapter = mAdapter.apply {
            setNewInstance(mViewModel.timeList)
            setOnItemClickListener { _, _, position ->
                index = position
                notifyDataSetChanged()
                mViewModel.chooseTime(position)
            }
        }
        mViewModel.toastObserver().autoDispose(scopeProvider).subscribe(this::toastObserver)

        mViewModel.startObserve().autoDispose(scopeProvider).subscribe {
            mTimeVB.lrvStartTime.setRightText(it)
        }

        mViewModel.endObserve().autoDispose(scopeProvider).subscribe {
            mTimeVB.lrvEndTime.setRightText(it)
        }

        mViewModel.historyLineObserver().autoDispose(scopeProvider).subscribe {
            var speed = binding.editThresholdSpeed.text.toString()
            if (speed.isEmpty()) speed = "0"
            startActivityTo<HistoryLineInfoActivity>(this) {
                putExtra(Keys.INTENT_TITLE, mViewModel.carName)
                putExtra(Keys.INTENT_CAR_ID, mViewModel.carId)
                putExtra(Keys.INTENT_OTHER, speed)
                putExtra(Keys.INTENT_DATA, mViewModel.params)
                putExtra(Keys.INTENT_TEAM_NAME, mViewModel.teamName)
                putExtra(Keys.VIDEO, mViewModel.videos)
            }
        }

        mViewModel.mileLive.observe(this) {
            setData(it)
        }


        val curYear = CalendarUtil.getCurYear()
        val curMonth = CalendarUtil.getCurMonth()
        val curDay = CalendarUtil.getCurDay()
        setCurCalender(curYear, curMonth, curDay)

        initCalendar()
    }

    private fun setParams() {
        val lineParams = ParamsUtil.getLineParams()
        binding.editThresholdSpeed.setText(lineParams?.get(0) ?: "100")
        binding.editThresholdStop.setText(lineParams?.get(1) ?: "5")
    }

    private fun initIntent() {
        val carId = intent.getStringExtra(Keys.INTENT_CAR_ID)
        val carName = intent.getStringExtra(Keys.INTENT_PLATE)
        if (carId == null) return
        mViewModel.carId = carId
        mViewModel.carName = carName ?: ""
        binding.lrvCar.setRightText(carName ?: "")
        binding.lrvCar.isEnabled = false
        mTimeVB.lrvChooseCar.setRightText(carName ?: "")
        mTimeVB.lrvChooseCar.isEnabled = false
        setDate()
    }

    override fun setListener() {
        binding.lrvCar.rightClick {
            toChooseCar()
        }

        mTimeVB.lrvChooseCar.rightClick {
            toChooseCar()
        }

        mTimeVB.lrvStartTime.rightClick {
            mViewModel.isStart = true
            mDatePicker.show(mTimeVB.lrvStartTime.getRightText())
        }
        mTimeVB.lrvEndTime.rightClick {
            mViewModel.isStart = false
            mDatePicker.show(mTimeVB.lrvEndTime.getRightText())
        }

        mSureVB.tvSure.filterFast {
            mViewModel.getHistory(
                if (binding.rdbCalendar.isChecked) calendarS else mTimeVB.lrvStartTime.getRightText(),
                if (binding.rdbCalendar.isChecked) calendarE else mTimeVB.lrvEndTime.getRightText(),
                binding.cbFilterStop.isChecked,
                binding.editThresholdSpeed.text.toString(),
                binding.editThresholdStop.text.toString(),
                binding.cbFilterInvalid.isChecked,
                binding.cbFilterAppend.isChecked
            )
            ParamsUtil.saveLineParams(
                binding.editThresholdSpeed.text.toString(),
                binding.editThresholdStop.text.toString()
            )
        }

        binding.rdbRunRun.setOnClickListener {
            mViewModel.isRunRun = true
        }
        binding.rdbRunStop.setOnClickListener {
            mViewModel.isRunRun = false
        }
        binding.rdbStopRun.setOnClickListener {
            mViewModel.isStopStop = true
        }
        binding.rdbStopStop.setOnClickListener {
            mViewModel.isStopStop = false
        }

        binding.rdbCalendar.setOnClickListener {
            binding.llCalendar.isVisible = true
            binding.llNormal.isVisible = false
            binding.lrvCar.isVisible = true
            binding.llBg.setBackgroundResource(R.color.color_CCD)
            binding.rgbType.isSelected = true
        }

        binding.rdbNormal.setOnClickListener {
            binding.llCalendar.isVisible = false
            binding.llNormal.isVisible = true
            binding.lrvCar.isVisible = false
            binding.llBg.setBackgroundResource(R.color.color_F9F)
            binding.rgbType.isSelected = false
        }

        binding.ivLegend.setOnClickListener {
            mPopup.showAtLocation(binding.root, Gravity.NO_GRAVITY, 0, 0)
        }

        binding.ivCalendarP.setOnClickListener {
            binding.calendarView.scrollToPre()
        }

        binding.ivCalendarN.setOnClickListener {
            if (changYM < curYM)
                binding.calendarView.scrollToNext()
        }
    }

    private fun toChooseCar() {
        if (NetDataUtil.isSyncTree) {
            launcher.launchAct<TeamsCarsActivity>(this) {
                putExtra("VideoCar", true)
            }
        } else {
            launcher.launchAct<ChooseCarActivity>(this) {
                putExtra("VideoCar", true)
            }
        }
    }

    private val launcher = registerResultOk { result ->
        result.data?.let {
            val carId = it.getStringExtra(Keys.INTENT_CAR_ID)
            val carName = it.getStringExtra(Keys.INTENT_CAR_NAME)
            val teamName = it.getStringExtra(Keys.INTENT_TEAM_NAME)
            val videos = it.getStringExtra(Keys.VIDEO)
            mTimeVB.lrvChooseCar.setRightText(carName ?: "")
            binding.lrvCar.setRightText(carName ?: "")
            mViewModel.carId = carId ?: ""
            mViewModel.carName = carName ?: ""
            mViewModel.teamName = teamName ?: ""
            mViewModel.videos = videos
            binding.tvMileTotal.isVisible = true
            setDate()
        }
    }


    private val mAdapter: ChooseTimeAdapter by lazy { ChooseTimeAdapter() }

    private val mDatePicker: CustomDatePicker by lazy {
        CustomDatePicker(
            this,
            callback,
            TimeUtil.normalDate,
            mViewModel.nowTimeFormat(),
            true
        ).apply {
            setCanShowPreciseTime(true)
        }
    }


    private val callback: CustomDatePicker.Callback = object : CustomDatePicker.Callback {
        override fun onTimeSelected(timestamp: Long) {
            mAdapter.index = -1
            mAdapter.notifyDataSetChanged()
            val time: String = DateFormatUtils.long2Str(timestamp, true)
            if (mViewModel.isStart) {
                mTimeVB.lrvStartTime.setRightText(time)
            } else {
                mTimeVB.lrvEndTime.setRightText(time)
            }
            mDatePicker.dismiss()
        }
    }

    private fun getYMDStr(year: Int, month: Int, day: Int): String {
        val nMonth = if (month < 10) "0$month" else "$month"
        val nDay = if (day < 10) "0$day" else "$day"
        return "$year$nMonth$nDay"
    }

    //////////////////////////////////////////////////////////
    private fun initCalendar() {
        binding.calendarView.setWeekStarWithMon()
        val curYear = binding.calendarView.curYear
        val curMonth = binding.calendarView.curMonth
        val curDay = binding.calendarView.curDay
        changYM = curYear * 100 + curMonth
        binding.ivCalendarN.isVisible = false
        binding.tvCalendarTime.text =
            "$curYear $yearDesc $curMonth $monthDesc"
        binding.tvMileTotal.text = "$total ---- ${getString(R.string.unit_mile)}"

        val date =
            "${curYear}-${if (curMonth < 10) "0$curMonth" else curMonth}-${if (curDay < 10) "0$curDay" else curDay}"
        calendarS = "$date 00:00"
        calendarE = "$date 23:59"
        binding.calendarView.setOnCalendarSelectListener(object : OnCalendarSelectListener {
            override fun onCalendarOutOfRange(calendar: Calendar?) {
            }

            override fun onCalendarSelect(calendar: Calendar, isClick: Boolean) {
                if (isClick) {
                    val year = calendar.year
                    val month = calendar.month
                    val day = calendar.day
                    val date =
                        "${year}-${if (month < 10) "0$month" else month}-${if (day < 10) "0$day" else day}"
                    calendarS = "$date 00:00"
                    calendarE = "$date 23:59"
                }
            }

        })
        binding.calendarView.setOnMonthChangeListener { year, month ->
            binding.tvCalendarTime.text = "$year $yearDesc $month $monthDesc"
            changYM = year * 100 + month
            binding.ivCalendarN.isVisible = changYM < curYM
            if (changYM < curYM) {
                val startDay = CalendarUtil.getYMStartDay(year, month)
                val endDay = CalendarUtil.getYMEndDay(year, month)
                val sDate = getYMDStr(year, month, startDay)
                val eDate = getYMDStr(year, month, endDay)
                mViewModel.getDayMile(sDate, eDate)
            } else if (changYM == curYM) {
                val startDay = CalendarUtil.getYMStartDay(year, month)
                val endDay = CalendarUtil.getYMEndDay(year, month)
                val sDate = getYMDStr(year, month, startDay)
                val eDate =
                    getYMDStr(
                        year, month,
                        if (month == curMonth && changYM == curYM) {
                            if (endDay < curDay) endDay else curDay
                        } else {
                            endDay
                        }
                    )
                mViewModel.getDayMile(sDate, eDate)
            } else {
                binding.tvMileTotal.text = ""
            }

        }

    }


    private fun setData(mile: DayMile) {
        binding.calendarView.clearSchemeDate()
        val map = HashMap<String, Calendar>()

        mile.list.forEach {
            val year = it.name.substring(0, 4).toInt()
            val month = it.name.substring(5, 7).toInt()

            val day = it.name.substring(8, 10).toInt()
            val mileD = (it.mile).toDouble()
            val calendar = getSchemeCalendar(year, month, day, Math.round(mileD).toString())
            map[calendar.toString()] = calendar
        }
        //此方法在巨大的数据量上不影响遍历性能，推荐使用

        binding.calendarView.setSchemeDate(map)
        binding.tvMileTotal.text = "$total " + Math.round(mile.mile.toDouble())
            .toString() + " ${getString(R.string.unit_mile)}"
    }


    private fun getSchemeCalendar(year: Int, month: Int, day: Int, text: String): Calendar {
        val calendar = Calendar()
        calendar.year = year
        calendar.month = month
        calendar.day = day
        calendar.scheme = text
        return calendar
    }


    private fun setCurCalender(year: Int, month: Int, day: Int) {
        binding.calendarView.scrollToCalendar(year, month, day)
    }

    private fun setDate() {
        val curYear = CalendarUtil.getCurYear()
        val curMonth = CalendarUtil.getCurMonth()
        val curDay = CalendarUtil.getCurDay()
        val lastDay = CalendarUtil.getYMStartDay(curYear, curMonth)
        val sTime = getYMDStr(curYear, curMonth, lastDay)
        val eTime = getYMDStr(curYear, curMonth, curDay)
        mViewModel.getDayMile(sTime, eTime)
        setCurCalender(curYear, curMonth, curDay)
    }


}